package com.uvstu.common.upay.pay;

import cn.uvtool.exception.TClientException;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayRequest;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.*;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.uvstu.common.pay.config.AlipayConfig;
import com.uvstu.common.upay.pay.config.AliPayConfigUtil;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付宝支付-工具类
 */
public class AliPayUtil {

    /**
     * PC网站支付
     * @param aliPayConfigUtil  支付宝配置
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @return
     * @throws TClientException
     */
    public static String pcPay(AliPayConfigUtil aliPayConfigUtil, String outTradeNo, String totalAmount, String subject) throws TClientException {
        AlipayClient alipayClient = aliPayConfigUtil.getAlipayClient();
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(aliPayConfigUtil.getReturnUrl());
        alipayRequest.setNotifyUrl(aliPayConfigUtil.getNotifyUrl());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no", outTradeNo);
        jsonObject.put("subject", subject);
        //电脑网站支付：FAST_INSTANT_TRADE_PAY    手机网站支付：QUICK_WAP_WAY
        jsonObject.put("product_code", "FAST_INSTANT_TRADE_PAY");
        jsonObject.put("total_amount", totalAmount);
        jsonObject.put("body", subject);
        jsonObject.put("timeout_express", "10m");
        alipayRequest.setBizContent(JSONObject.toJSONString(jsonObject));
        try {
            String form = (alipayClient.pageExecute((AlipayRequest) alipayRequest)).getBody();
            System.out.println("form==>" + form);
            return form;
        } catch (AlipayApiException e) {
            throw new TClientException("支付宝支付调用失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * H5网站支付
     * @param aliPayConfigUtil  支付宝配置
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @return
     * @throws TClientException
     */
    public static String wapPay(AliPayConfigUtil aliPayConfigUtil,String outTradeNo, String totalAmount, String subject) throws TClientException {
        AlipayClient alipayClient = aliPayConfigUtil.getAlipayClient();
        AlipayTradeWapPayRequest wapPayRequest = new AlipayTradeWapPayRequest();
        wapPayRequest.setReturnUrl(aliPayConfigUtil.getReturnUrl());
        wapPayRequest.setNotifyUrl(aliPayConfigUtil.getNotifyUrl());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("out_trade_no", outTradeNo);
        jsonObject.put("subject", subject);
        //电脑网站支付：FAST_INSTANT_TRADE_PAY    手机网站支付：QUICK_WAP_WAY
        jsonObject.put("product_code", "QUICK_WAP_WAY");
        jsonObject.put("total_amount", totalAmount);
        jsonObject.put("body", subject);
        jsonObject.put("timeout_express", "10m");
        wapPayRequest.setBizContent(JSONObject.toJSONString(jsonObject));
        try {
            String form = (alipayClient.pageExecute((AlipayRequest) wapPayRequest)).getBody();
            return form;
        } catch (AlipayApiException e) {
            throw new TClientException("支付宝支付调用失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 扫码支付
     *
     * @param outTradeNo     平台订单号
     * @param totalAmount    总金额
     * @param subject        标题
     * @return
     * @throws com.uvstu.common.pay.exception.TClientException
     */
    public static String qrPay(AliPayConfigUtil aliPayConfigUtil,String outTradeNo, String totalAmount, String subject) throws com.uvstu.common.pay.exception.TClientException, TClientException {
        AlipayClient alipayClient = aliPayConfigUtil.getAlipayClient();
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        request.setReturnUrl(aliPayConfigUtil.getReturnUrl());
        request.setNotifyUrl(aliPayConfigUtil.getNotifyUrl());
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", outTradeNo);
        bizContent.put("total_amount", totalAmount);
        bizContent.put("subject", subject);
        request.setBizContent(bizContent.toString());
        try{
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                return response.getQrCode();
            } else {
                throw new TClientException("支付宝支付第三方参数错误!");
            }
        }catch (Exception e){
            throw new TClientException("支付宝支付调用失败！错误信息：" + e.getMessage());
        }
    }


    /**
     * 支付宝支付通知结果解析
     * @param request
     * @return
     */
    public Map<String, String> aliPayNotify(HttpServletRequest request){
        try{
            Map<String, String> params = new HashMap();
            Map<String, String[]> requestParams = request.getParameterMap();
            Iterator<String> iter = requestParams.keySet().iterator();

            while(iter.hasNext()) {
                String name = (String)iter.next();
                String[] values = (String[])requestParams.get(name);
                String valueStr = "";
                for(int i = 0; i < values.length; ++i) {
                    valueStr = i == values.length - 1 ? valueStr + values[i] : valueStr + values[i] + ",";
                }
                valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
            return params;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 支付查询
     *
     * @param aliPayConfigUtil  支付宝配置
     * @param outTradeNo 平台订单号
     * @param tradeNo    支付宝交易号
     * @return
     * @throws TClientException
     */
    public static Map<String, Object> payQuery(AliPayConfigUtil aliPayConfigUtil,String outTradeNo, String tradeNo) throws TClientException {
        try {
            AlipayClient alipayClient = aliPayConfigUtil.getAlipayClient();
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            //商户订单号
            model.setOutTradeNo(outTradeNo);
            //支付宝交易号
            model.setTradeNo(tradeNo);
            request.setBizModel(model);
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                JSONObject result = (JSONObject) JSONObject.parse(response.getBody());
                return result;
            } else {
                throw new TClientException("支付宝订单查询失败！状态码：" + response.isSuccess());
            }
        } catch (Exception e) {
            throw new TClientException("支付宝订单查询失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 退款
     *
     * @param aliPayConfigUtil  支付宝配置
     * @param outTradeNo   商户订单号
     * @param tradeNo      支付宝交易号
     * @param refundAmount 退款金额
     * @param refundReason 退款原因
     * @return
     * @throws TClientException
     */
    public static Map<String, Object> refund(AliPayConfigUtil aliPayConfigUtil,String outTradeNo, String tradeNo, String refundAmount, String refundReason) throws TClientException {
        try {
            AlipayClient alipayClient = aliPayConfigUtil.getAlipayClient();
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            JSONObject bizContent = new JSONObject();
            bizContent.put("trade_no", tradeNo);
            bizContent.put("refund_amount", refundAmount);
            bizContent.put("out_request_no", outTradeNo);
            bizContent.put("refund_reason", refundReason);
            System.out.println("退款参数入参："+JSONObject.toJSONString(bizContent));
            request.setBizContent(bizContent.toString());
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if(response.isSuccess()){
                System.out.println("调用成功");
                JSONObject result = JSONObject.parse(response.getBody());
                System.out.println("退款参数出参："+JSONObject.toJSONString(result));
                return result;
            } else {
                System.out.println("调用失败");
                throw new TClientException("支付宝订单退款失败!");
            }
        } catch (Exception e) {
            throw new TClientException("支付宝订单退款失败！错误信息：" + e.getMessage());
        }
    }

    /**
     * 退款查询
     *
     * @param aliPayConfigUtil  支付宝配置
     * @param outTradeNo 商户订单号
     * @param tradeNo    支付宝交易号
     * @return
     * @throws TClientException
     */
    public static Map<String, Object> refundQuery(AliPayConfigUtil aliPayConfigUtil,String outTradeNo, String tradeNo) throws TClientException {
        try {
            AlipayClient alipayClient = aliPayConfigUtil.getAlipayClient();
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();
            //支付宝交易号
            model.setTradeNo(tradeNo);
            //商户订单号
            model.setOutTradeNo(outTradeNo);
            //退款请求号。 请求退款接口时，传入的退款请求号，如果在退款请求时未传入，则该值为创建交易时的商户订单号。
            model.setOutRequestNo(outTradeNo);
            request.setBizModel(model);
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
            System.out.println(response.getBody());
            if (response.isSuccess()) {
                JSONObject result = (JSONObject) JSONObject.parse(response.getBody());
                return result;
            } else {
                throw new TClientException("支付宝订单退款查询失败！");
            }
        } catch (Exception e) {
            throw new TClientException("支付宝订单退款查询失败！错误信息：" + e.getMessage());
        }
    }

}
